<script setup>
import api from '@/api';
import connectedImg from '@/assets/images/connected.png';
import unconnectedImg from '@/assets/images/unconnected.png';
import { useDataStore } from '@/stores/modules/data';
import utils from '@/utils';
import HomePortLocalForwardManage from '@/views/HomePortLocalForwardManage.vue';
import HomeSSHTunnelManage from '@/views/HomeSSHTunnelManage.vue';
import HomeSSHTunnelSwitch from '@/views/HomeSSHTunnelSwitch.vue';
import HomeTagManage from '@/views/HomeTagManage.vue';
import MyDialog from '@/views/MyDialog.vue';
import { computed, onMounted, onUnmounted, ref } from 'vue';
const dataStore = useDataStore();
// 表格数据
const tableData = ref([]);

// 右键菜单相关
const contextMenuVisible = ref(false);
const contextMenuPosition = ref({ x: 0, y: 0 });
const contextMenuRow = ref(null);

// 对话框显示状态
const dialogVisible = ref(false);
const dialogTitle = ref('');


// 标签选项
const tagsOptions = ref([]);

onMounted(async () => {
  const res = await api.tag.getTagList();
  tagsOptions.value = res.data.map(item => item.name);
});

const freshTags = async () => {
  const res = await api.tag.getTagList();
  tagsOptions.value = res.data.map(item => item.name);
};
const tableDataFiltered = computed(() => {
  return tableData.value.filter(item => {
    return dataStore.tags.length === 0 || item.tags.some(tag => dataStore.tags.includes(tag));
  });
});


const selectedRowIds = ref([]);
const selectedRows = computed(() => {
  return tableDataFiltered.value.filter(item => selectedRowIds.value.includes(item.id));
});

// 处理卡片复选框变化
const handleCardCheckboxChange = (id, checked) => {
  if (checked) {
    if (!selectedRowIds.value.includes(id)) {
      selectedRowIds.value.push(id);
    }
  } else {
    selectedRowIds.value = selectedRowIds.value.filter(item => item !== id);
  }
};



// 加载数据
const loadData = async () => {
  const res = await api.portLocalForward.getPortLocalForwardList();
  tableData.value = res.data.map(item => ({
    ...item,
    tags: item.tags ? item.tags.split(',').map(tag => tag.trim()).filter(tag => tag) : []
  }));
  // 模拟数据更新
};

const editData = ref(null)
const editBaseMessage = ref(false);
// 新增隧道
const handleAdd = () => {
  dialogTitle.value = '新增端口转发';
  editData.value = {};
  editBaseMessage.value = false;
  dialogVisible.value = true;
};

// 编辑隧道
const handleEdit = (row) => {
  dialogTitle.value = '编辑端口转发';
  editData.value = { ...row }
  editBaseMessage.value = row.status === 1;
  dialogVisible.value = true;
};


// 复制连接信息
const handleCopy = (row) => {
  dialogTitle.value = '复制端口转发';
  editData.value = { ...row, id: '', name: `${row.name}-副本` };
  editBaseMessage.value = false;
  dialogVisible.value = true;
};

// 删除隧道
const handleDelete = async (row) => {
  if (row.status === 1) {
    utils.message.warning('启动中的端口转发不能进行删除操作');
    return;
  }
  await utils.message.confirm(`是否确认删除端口转发 "${row.name}"`);
  try {
    await api.portLocalForward.deletePortLocalForward(row.id);
    utils.message.success('删除成功');
    loadData();
  } catch {
    utils.message.info('已取消删除');
  }
};



onMounted(() => {
  loadData();
  document.addEventListener('click', handleDocumentClick);
  document.addEventListener('keydown', handleKeyDown);
});

onUnmounted(() => {
  document.removeEventListener('click', handleDocumentClick);
  document.removeEventListener('keydown', handleKeyDown);
});

const dialogVisibleSsh = ref(false);
// 新增SSH隧道
const handleSshTunnelManage = () => {
  dialogVisibleSsh.value = true;
};

const dialogVisibleTag = ref(false);
const handleTagManage = () => {
  dialogVisibleTag.value = true;
};



const handleSubmit = () => {
  loadData();
  dialogVisible.value = false;
};

const handleStatusChange = async (row) => {
  if (row.status === 1) {
    await api.portLocalForward.stopPortLocalForward([row.id]);
    utils.message.success('停止成功');
  } else {
    const { data } = await api.portLocalForward.startPortLocalForward([row.id]);
    if (data.length > 0) {
      utils.message.error(data[0][1]);
    } else {
      utils.message.success('启动成功');
    }
  }
  loadData();
};



const handleStart = async () => {
  let ids = getIds();
  if (ids.length === 0) {
    utils.message.warning('请选择要启动的端口转发');
    return;
  }
  const { data } = await api.portLocalForward.startPortLocalForward(ids);
  if (data.length > 0) {
    for (let o of data) {
      utils.message.error(`${o[0]}启动失败：${o[1]}`);
    }
  } else {
    utils.message.success('启动成功');
  }
  loadData();
};

const handleStop = async () => {
  let ids = getIds();
  if (ids.length === 0) {
    utils.message.warning('请选择要关闭的端口转发');
    return;
  }
  await api.portLocalForward.stopPortLocalForward(ids);
  utils.message.success('关闭成功');
  loadData();
};

const dialogVisibleSshTunnelSwitch = ref(false);
const handleSwitchSshTunnel = () => {
  let ids = getIds();
  if (ids.length === 0) {
    utils.message.warning('请选择要切换SSH隧道的端口转发');
    return;
  }
  // 判断ids中是否有启动中的端口转发
  const hasRunning = ids.map(id => tableData.value.find(item => item.id === id)).some(item => item && item.status === 1);
  if (hasRunning) {
    utils.message.warning('启动中的端口转发不能进行切换SSH隧道操作');
    return;
  }
  dialogVisibleSshTunnelSwitch.value = true;
};

function getIds() {
  let ids = []
  if (selectedRows.value.length !== 0) {
    ids = selectedRows.value.map(item => item.id);
  } else if (tableDataFiltered.value.length !== 0) {
    ids = tableDataFiltered.value.map(item => item.id);
  }
  return ids;
}

const handleSwitchSshTunnelSubmit = async (sshTunnelId) => {
  let ids = getIds();
  if (ids.length === 0) {
    utils.message.warning('请选择要切换SSH隧道的端口转发');
    return;
  }
  await api.portLocalForward.switchSshTunnel(ids, sshTunnelId);
  utils.message.success('切换SSH隧道成功');
  loadData();
  dialogVisibleSshTunnelSwitch.value = false;
};

// 处理右键菜单
const handleContextMenu = (event, row) => {
  event.preventDefault();
  contextMenuRow.value = row;

  // 计算菜单位置，确保不会超出屏幕
  const menuWidth = 120;
  const menuHeight = 180;
  let x = event.clientX;
  let y = event.clientY;

  // 如果菜单会超出右边界，则靠左显示
  if (x + menuWidth > window.innerWidth) {
    x = window.innerWidth - menuWidth - 10;
  }

  // 如果菜单会超出下边界，则靠上显示
  if (y + menuHeight > window.innerHeight) {
    y = window.innerHeight - menuHeight - 10;
  }

  contextMenuPosition.value = { x, y };
  contextMenuVisible.value = true;
};

// 关闭右键菜单
const closeContextMenu = () => {
  contextMenuVisible.value = false;
  contextMenuRow.value = null;
};

// 点击其他地方关闭菜单
const handleDocumentClick = (event) => {
  const contextMenu = document.querySelector('.context-menu');
  if (contextMenu && !contextMenu.contains(event.target) && contextMenuVisible.value) {
    closeContextMenu();
  }
};

// 处理键盘 ESC 键关闭菜单
const handleKeyDown = (event) => {
  if (event.key === 'Escape' && contextMenuVisible.value) {
    closeContextMenu();
  }
};

// 右键菜单项点击处理
const handleMenuAction = (action) => {
  if (!contextMenuRow.value) return;

  const row = contextMenuRow.value;
  // 如果处于启动中状态，禁止删除操作
  if ((action === 'delete') && row.status === 1) {
    return;
  }
  switch (action) {
    case 'edit':
      handleEdit(row);
      break;
    case 'delete':
      handleDelete(row);
      break;
    case 'copy':
      handleCopy(row);
      break;
    case 'toggle':
      handleStatusChange(row);
      break;
  }
  closeContextMenu();
};

const getTrueUrl = (row) => {
  return row.url || `http://localhost:${row.localPort}`;
}
const openLink = (row) => {
  if (row.status !== 1) {
    return;
  }
  window.open(getTrueUrl(row), '_blank');
};

</script>

<template>
  <div class="home-view-container">
    <el-form label-width="auto" inline class="home-view-form">
      <el-form-item label="标签搜索">
        <el-select v-model="dataStore.tags" multiple clearable collapse-tags placeholder="请选择标签" style="width: 200px;">
          <el-option v-for="item in tagsOptions" :key="item" :label="item" :value="item" />
        </el-select>
      </el-form-item>
      <el-form-item>
        <el-button type="success" @click="handleStart" icon="VideoPlay">
          批量启动
        </el-button>
        <el-button type="info" @click="handleStop" icon="VideoPause">
          批量关闭
        </el-button>
        <el-divider direction="vertical" />
        <el-button type="primary" @click="handleSwitchSshTunnel" icon="Switch">
          隧道切换
        </el-button>
        <el-divider direction="vertical" />
        <el-button type="primary" @click="handleSshTunnelManage" icon="Folder">
          隧道管理
        </el-button>
        <el-button type="primary" @click="handleTagManage" icon="CollectionTag">
          标签管理
        </el-button>
        <el-button type="primary" @click="handleAdd" icon="Plus">
          新增转发
        </el-button>
      </el-form-item>
    </el-form>
    <div class="home-view-content">
      <el-empty v-if="tableDataFiltered.length === 0" description="暂无数据" :image-size="100" />
      <el-scrollbar v-else>
        <div class="home-view-content-inner">
          <el-card v-for="row in tableDataFiltered" :key="row.id" class="port-forward-card"
            :class="{ 'card-connected': row.status === 1, 'card-disconnected': row.status === 0 }" shadow="hover"
            @contextmenu.prevent="handleContextMenu($event, row)">
            <template #header>
              <div class="card-header">
                <div class="card-title-section">
                  <el-checkbox :model-value="selectedRowIds.includes(row.id)"
                    @change="(val) => handleCardCheckboxChange(row.id, val)" class="card-checkbox" />
                  <span class="card-title">{{ row.name }}</span>
                </div>
                <img :src="row.status === 1 ? connectedImg : unconnectedImg" alt="status" class="status-image" />
              </div>
            </template>
            <div class="card-content">
              <div class="card-item">
                <span class="card-label">本地端口:</span>
                <span class="card-value">{{ row.localPort }}</span>
              </div>
              <div class="card-item">
                <span class="card-label">远程主机:</span>
                <span class="card-value">{{ row.remoteHost }}:{{ row.remotePort }}</span>
              </div>
              <div class="card-item">
                <span class="card-label">SSH隧道:</span>
                <span class="card-value">{{ row.sshTunnelName || '未设置' }}</span>
              </div>
              <div class="card-item">
                <span class="card-label">访问地址:</span>
                <span class="card-value " :title="getTrueUrl(row)" :class="{ link: row.status === 1 }"
                  @click="openLink(row)">{{
                    getTrueUrl(row) }}</span>
              </div>
            </div>
            <div class="card-footer">
              <div class="card-tags" v-if="row.tags.length > 0">
                <el-tag v-for="tag in row.tags" :key="tag" size="small" class="tag-item">
                  {{ tag }}
                </el-tag>
              </div>
              <div v-else class="card-tags-empty">
                <span class="empty-text">暂无标签</span>
              </div>
            </div>
          </el-card>
        </div>
      </el-scrollbar>
    </div>
  </div>
  <MyDialog v-model="dialogVisible" :title="dialogTitle" width="800px">
    <HomePortLocalForwardManage :edit-data="editData" :edit-base-message="editBaseMessage"
      @cancel="() => { dialogVisible = false }" @submit="handleSubmit" />
  </MyDialog>
  <MyDialog v-model="dialogVisibleSsh" title="SSH隧道管理" width="1000px">
    <HomeSSHTunnelManage />
  </MyDialog>
  <MyDialog v-model="dialogVisibleSshTunnelSwitch" title="切换SSH隧道" width="600px">
    <HomeSSHTunnelSwitch @cancel="() => { dialogVisibleSshTunnelSwitch = false }"
      @submit="handleSwitchSshTunnelSubmit" />
  </MyDialog>
  <MyDialog v-model="dialogVisibleTag" title="标签管理" width="600px">
    <HomeTagManage @freshTags="freshTags" />
  </MyDialog>
  <!-- 右键菜单 -->
  <div v-if="contextMenuVisible" class="context-menu"
    :style="{ left: contextMenuPosition.x + 'px', top: contextMenuPosition.y + 'px' }">
    <div class="context-menu-item" @click="handleMenuAction('toggle')">
      <el-icon>
        <component :is="contextMenuRow?.status === 1 ? 'VideoPause' : 'VideoPlay'" />
      </el-icon>
      <span>{{ contextMenuRow?.status === 1 ? '停止' : '启动' }}</span>
    </div>
    <div class="context-menu-item" @click="handleMenuAction('edit')">
      <el-icon>
        <Edit />
      </el-icon>
      <span>编辑</span>
    </div>
    <div class="context-menu-item" @click="handleMenuAction('copy')">
      <el-icon>
        <CopyDocument />
      </el-icon>
      <span>复制</span>
    </div>
    <div class="context-menu-divider"></div>
    <div class="context-menu-item danger" :class="{ disabled: contextMenuRow?.status === 1 }"
      @click="handleMenuAction('delete')">
      <el-icon>
        <Delete />
      </el-icon>
      <span>删除</span>
    </div>
  </div>
</template>

<style scoped lang="scss">
.home-view-container {
  // padding: 20px;
  height: 100%;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;

  .home-view-form {
    padding: 20px 20px 0 20px;
  }

  .home-view-content-toolbar {
    padding: 0 20px 20px 20px;
  }

  .home-view-content {
    flex: 1;
    min-height: 0;
    padding: 0 0 20px 0;


    .home-view-content-inner {
      display: grid;
      grid-template-columns: repeat(4, 1fr);
      grid-auto-rows: min-content;
      gap: 20px;
      padding: 0 20px 0 20px;
    }
  }
}



.port-forward-card {
  display: flex;
  flex-direction: column;
  height: auto;
  transition: all 0.3s ease;

  // 已连接状态样式
  &.card-connected {
    border: 2px solid var(--el-color-success);
    background: linear-gradient(to bottom, rgba(103, 194, 58, 0.05), transparent);

    .card-header {
      .card-title {
        color: var(--el-color-success);
      }
    }

    .card-footer {
      border-top-color: var(--el-color-success-light-7);
    }

    &:hover {
      border-color: var(--el-color-success-dark-2);
      box-shadow: 0 2px 12px 0 rgba(103, 194, 58, 0.2);
    }
  }

  // 未连接状态样式
  &.card-disconnected {
    border: 2px solid var(--el-border-color);
    background: linear-gradient(to bottom, rgba(0, 0, 0, 0.02), transparent);
    opacity: 0.85;

    .card-header {
      .card-title {
        color: var(--el-text-color-secondary);
      }
    }

    .card-footer {
      border-top-color: var(--el-border-color-lighter);
    }

    &:hover {
      border-color: var(--el-border-color-dark);
      opacity: 1;
      box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
    }
  }

  .card-header {
    display: flex;
    justify-content: space-between;
    align-items: center;

    .card-title-section {
      display: flex;
      align-items: center;
      flex: 1;
      min-width: 0;
      gap: 8px;

      .card-checkbox {
        flex-shrink: 0;
      }

      .card-title {
        font-weight: 600;
        font-size: 14px;
        color: var(--el-text-color-primary);
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
        flex: 1;
      }
    }

    .status-image {
      flex-shrink: 0;
      margin-left: 8px;
      width: 20px;
      height: 20px;
      object-fit: contain;
      cursor: default;
    }
  }

  .card-content {
    flex: 0 1 auto;
    padding: 0px 0px 12px;

    .card-item {
      display: flex;
      margin-bottom: 8px;
      font-size: 13px;

      &:last-child {
        margin-bottom: 0;
      }

      .card-label {
        color: var(--el-text-color-secondary);
        min-width: 80px;
        flex-shrink: 0;
      }

      .card-value {
        color: var(--el-text-color-primary);
        flex: 1;
        word-break: break-all;
        /* 核心：单行文本省略样式 */
        white-space: nowrap;
        /* 禁止换行 */
        overflow: hidden;
        /* 隐藏超出部分 */
        text-overflow: ellipsis;
        /* 超出显示省略号 */

        &.link {
          color: var(--el-color-primary);
          cursor: pointer;

          &:hover {
            text-decoration: underline;
          }
        }
      }
    }
  }

  .card-footer {
    border-top: 1px solid var(--el-border-color-lighter);
    padding-top: 12px;
    margin-top: auto;

    .card-tags {
      display: flex;
      flex-wrap: wrap;
      gap: 6px;
      align-items: center;

      .tag-item {
        margin: 0;
        font-size: 12px;
      }
    }

    .card-tags-empty {
      display: flex;
      align-items: center;
      min-height: 24px;

      .empty-text {
        font-size: 12px;
        color: var(--el-text-color-placeholder);
      }
    }
  }

  .action-wrap {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
  }
}

.context-menu {
  position: fixed;
  background: #fff;
  border: 1px solid var(--el-border-color);
  border-radius: 4px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  padding: 4px 0;
  min-width: 120px;
  z-index: 9999;

  .context-menu-item {
    display: flex;
    align-items: center;
    padding: 8px 16px;
    cursor: pointer;
    font-size: 14px;
    color: var(--el-text-color-primary);
    transition: background-color 0.2s;

    &:hover {
      background-color: var(--el-fill-color-light);
    }

    &.danger {
      color: var(--el-color-danger);

      &:hover {
        background-color: var(--el-color-danger-light-9);
      }
    }

    &.disabled {
      color: var(--el-text-color-disabled);
      cursor: not-allowed;
      opacity: 0.5;

      &:hover {
        background-color: transparent;
      }

      &.danger {
        color: var(--el-text-color-disabled);

        &:hover {
          background-color: transparent;
        }
      }
    }

    .el-icon {
      margin-right: 8px;
      font-size: 16px;
    }
  }

  .context-menu-divider {
    height: 1px;
    background-color: var(--el-border-color-lighter);
    margin: 4px 0;
  }
}
</style>
